package nettyProtocol.serverAndClient;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.ReadTimeoutHandler;
import nettyProtocol.code.NettyMessageDecoder;
import nettyProtocol.code.NettyMessageEncoder;
import nettyProtocol.handshakeAndAuthentication.LoginAuthRespHandler;
import nettyProtocol.wather.HeartBeatRespHandler;

public abstract class NettyServer {
    public void bind() throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 100)
                .handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new ChildChannelHandler());
//        initChannel0(b);
        ChannelFuture f = b.bind("127.0.0.1", 9000).sync();
        System.out.println("Netty server start ok :" + (NettyConstant.REMOTEIP + ":" + NettyConstant.PORT));

        f.channel().closeFuture().sync();
    }

    public abstract void initChannel(ChannelPipeline pipeline);

    /**
     * 字类可以覆盖写
     * @throws Exception
     */
    protected void initChannel0(ChannelPipeline pipeline) {
        this.initChannel(pipeline);
    }


    public class ChildChannelHandler extends ChannelInitializer<SocketChannel> {
        @Override
        protected  void initChannel(SocketChannel ch) throws Exception {
            //解码器
            ch.pipeline().addLast( new NettyMessageDecoder(1024 * 1024, 4, 4, -8, 0));
            //编码
            ch.pipeline().addLast(new NettyMessageEncoder());
            ch.pipeline().addLast(new ReadTimeoutHandler(50));
            //接入认证
            ch.pipeline().addLast(new LoginAuthRespHandler());
            //心跳响应
            ch.pipeline().addLast(new HeartBeatRespHandler());
            initChannel0(ch.pipeline());
        }
    }
}
